<?php

namespace Application\System\Controller;

use Aoe\Attributes\Controller\HttpMust;
use Aoe\Attributes\Controller\SetResponse;
use Aoe\Attributes\Controller\Super;
use Aoe\Attributes\Controller\Trace;
use Aoe\Core\Controller;
use Aoe\Emulator\Controller\Spa;
use Aoe\Emulator\Ifc\Vu;
use Aoe\Intent\Request\Http;
use Aoe\Intent\Request\Request;
use Aoe\Intent\User\Power;
use Aoe\Intent\User\User;
use Aoe\Util\Bus\Store\Obj;

/**
 * # 管理后台
 *
 * @noinspection PhpUnused
 */
#[Trace]
#[Super(false)]
#[SetResponse(Spa::class)]
class Surface extends Controller
{
    /**
     * ## 界面-后台
     *
     * @noinspection PhpUnused
     */
    #[HttpMust]
    protected function index_action(Http $http): void
    {
        $config = $this->kernel->config;
        $user = $http->user;
        $http->response->complete([
            Vu::COMPONENT => 'main',
            Vu::SCHEMA    => [
                'menu'     => $http->url->makeUrl('/aoe/surface/menus'),
                'logout'   => $http->url->makeUrl('/auth/admin/logout'),
                'settings' => [
                    'app'     => $config->get('app'),
                    'company' => $config->get('company'),
                    'soft'    => $config->get('soft'),
                    'version' => $config->get('version'),
                ],
                'user' => [
                    'name' => $user->name,
                    'home' => $http->url->makeUrl($user->home ?? '/aoe/surface/home'),
                ],
            ],
        ]);
    }
    
    /**
     * ## 接口-工作台
     * @noinspection PhpUnused
     */
    protected function home_action(Request $request): void
    {
        $request->response->complete(
            [
                Vu::COMPONENT => 'red',
            ],
        );
    }
    
    /**
     * ## 接口-菜单
     * @noinspection PhpUnused
     */
    protected function menus_action(Http $http): void
    {
        if ($http->user->isAdministrator()) {
            // 权限管理
            $ms[] = [
                "id"    => "659da2d5-fee6-463e-9e5f-2497ac98af4f",
                "label" => "权限管理",
                "icon"  => "user",
                'items' => [
                    [
                        'id'    => "659da2d5-fee6-463e-9e5f-2497ac98af5f",
                        "label" => "用户管理",
                        "url"   => $http->url->makeUrl("auth/admin/list"),
                    ],
                    [
                        'id' => "659da2d5-fee6-463e-9e5f-2497ac98af6f",
                        "label" => "资源管理",
                        "url"   => $http->url->makeUrl("auth/resource/list"),
                    ],
                    [
                        'id' => "659da2d5-fee6-463e-9e5f-2497ac98af7f",
                        "label" => "角色管理",
                        "url"   => $http->url->makeUrl("auth/role/list"),
                    ],
                    [
                        'id' => "659da2d5-fee6-463e-9e5f-2497ac98af3f",
                        "label" => "日志管理",
                        "url"   => $http->url->makeUrl("auth/record/list"),
                    ],
                ]
            ];
            
            // 模块管理
            $ms[] = [
                'id'    => "fea5af30-46fc-460f-8d0c-19bd16bcdd26",
                "label" => "模块管理",
                "url"   => $http->url->makeUrl("aoe/create/index"),
                'icon'  => 'menu-application'
            ];
            
            // 系统配置
            $ms[] = [
                'id'    => "da5a5e26-6137-4bfe-a8f8-f7527139bb78",
                "label" => "系统配置",
                "icon"  => 'setting',
                "url"   => $http->url->makeUrl("aoe/settings/index")
            ];
            
            // 菜单管理
            $ms[] = [
                "id"    => "fa5a5e26-5137-4bfe-a8f8-f7527139bb7e",
                "label" => "菜单管理",
                "icon"  => 'menu',
                "url"   => $http->url->makeUrl("aoe/menu/tree")
            ];
            
            $http->response->complete($ms);
            return;
        }
        
        $r = $http->channel(
            'aoe/menu/load',
            [
                'compiler' => fn(string $str) => $this->_compile($http, $str),
            ],
        );
        
        $http->response->complete(
            empty($r->getValue()) ? [] : $this->_filter_menu($http, json_decode($r->getValue(), true))
        );
    }
    
    /**
     * ### 内部-菜单编译
     */
    private function _compile(Http $http, string $str): string
    {
        $o1 = json_decode($str, true);
        if (!is_array($o1)) return '[]';
        
        $fn = function ($n) use ($http, &$fn) {
            $copy = $n;
            if (isset($n['url'])) $copy['url'] = $http->compileUrl($n['url']);
            
            if (isset($n['children'])) {
                unset($copy['children']);
                $copy['items'] = array_map($fn, $n['children']);
            }
            
            return $copy;
        };
        
        return Obj::json(array_map($fn, $o1));
    }
    
    /**
     * ### 内部-过滤权限菜单
     *
     * @param Http $http
     * @param array   $menus
     *
     * @return array
     */
    private function _filter_menu(Http $http, array $menus): array
    {
        $user = $http->user;
        if ($user->isAdministrator()) return $menus;
        
        $ms = [];
        
        foreach ($menus as $menu) {
            if (!$this->_check_menu_auth($user, $menu)) continue;
            
            $ms[] = $menu;
            if (!isset($menu['items'])) continue;
            
            $items = array_filter($menu['items'], fn (array $item) => $this->_check_menu_auth($user, $item));
            if (empty($items)) continue;
            
            $menu['items'] = $items;
            $ms[] = $menu;
        }
        
        return $ms;
    }
    
    /**
     * ### 内部-权限检查
     *
     * @param User  $user
     * @param array $item
     *
     * @return bool
     */
    private function _check_menu_auth(User $user, array $item): bool
    {
        return !isset($item['auth']) || $user->hasNormalPower($item['auth'], Power::READ);
    }
}